#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <stdbool.h>

typedef struct Node {
    void        *value;
    struct Node *prev;
    struct Node *next;
} Node;

typedef struct {
    Node head;
    int  size;
    int  (*match)(void *, void *);
    void (*freeValue)(void *);
} LinkedList;

typedef struct {
    LinkedList *linked_list;
    Node       *node;
} LinkedListIterator;

LinkedList         *linked_list_create();
void                linked_list_free(LinkedList *linked_list);
void                linked_list_reset(LinkedList *linked_list);
void               *linked_list_get(const LinkedList *linked_list, void *value);
void               *linked_list_get_l(LinkedList *linked_list);
void               *linked_list_get_r(LinkedList *linked_list);
void                linked_list_add_l(LinkedList *linked_list, void *value);
void                linked_list_add_r(LinkedList *linked_list, void *value);
void                linked_list_remove_node(LinkedList *linked_list, Node *node);
void                linked_list_full_remove_node(LinkedList *linked_list, Node *node);
void               *linked_list_pop(LinkedList *linked_list, void *value);
void               *linked_list_pop_l(LinkedList *linked_list);
void               *linked_list_pop_r(LinkedList *linked_list);
void                linked_list_push_back(LinkedList *linked_list, Node *node);
LinkedListIterator *linked_list_iterator_create(LinkedList *linked_list);
void                linked_list_iteraotr_reset(LinkedListIterator *iterator);
Node               *linked_list_iterator_next(LinkedListIterator *iterator);
void                linked_list_iterator_free(LinkedListIterator *iterator);
int                 linked_list_len(LinkedList *linked_list);
bool                linked_list_is_empty(const LinkedList *linked_list);

#endif // LINKEDLIST_H
